home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / alpha.arc / AX25CMD.C < prev    next >
C/C++ Source or Header  |  1988-07-24  |  12KB  |  555 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "mbuf.h"
  4. #include "ax25.h"
  5. #include "timer.h"
  6. #include "iface.h"
  7. #include "lapb.h"
  8. #include "cmdparse.h"
  9. #include "session.h"
  10.  
  11. char *ax25states[] = {
  12.     "Disconnected",
  13.     "Conn pending",
  14.     "Disc pending",
  15.     "Connected",
  16.     "Recovery",
  17.     "Frame Reject",
  18. };
  19.  
  20. int domycall(),dodigipeat(),doaxstat(),dot1(),dot2(),dot3(),domaxframe(),
  21.     doaxwindow(),dopaclen(),don2(),doaxreset(),dopthresh();
  22.  
  23. static struct cmds axcmds[] = {
  24.     "digipeat",    dodigipeat,    0, NULLCHAR,    NULLCHAR,
  25.     "maxframe",    domaxframe,    0, NULLCHAR,    NULLCHAR,
  26.     "mycall",    domycall,    0, NULLCHAR,    NULLCHAR,
  27.     "paclen",    dopaclen,    0, NULLCHAR,    NULLCHAR,
  28.     "pthresh",    dopthresh,    0, NULLCHAR,    NULLCHAR,
  29.     "reset",    doaxreset,    2, "ax25 reset <axcb>", NULLCHAR,
  30.     "retry",    don2,        0, NULLCHAR,    NULLCHAR,
  31.     "status",    doaxstat,    0, NULLCHAR,    NULLCHAR,
  32.     "t1",        dot1,        0, NULLCHAR,    NULLCHAR,
  33.     "t2",        dot2,        0, NULLCHAR,    NULLCHAR,
  34.     "t3",        dot3,        0, NULLCHAR,    NULLCHAR,
  35.     "window",    doaxwindow,    0, NULLCHAR,    NULLCHAR,
  36.     NULLCHAR,    NULLFP,        0, "ax25 subcommands: digipeat maxframe mycall paclen reset retry status\n\tt1 t2 t3 window",    NULLCHAR,
  37. };
  38. /* Multiplexer for top-level ax25 command */
  39. doax25(argc,argv)
  40. int argc;
  41. char *argv[];
  42. {
  43.     return subcmd(axcmds,argc,argv);
  44. }
  45.  
  46. static
  47. doaxreset(argc,argv)
  48. int argc;
  49. char *argv[];
  50. {
  51.     struct ax25_cb *axp;
  52.     extern char notval[];
  53.  
  54.     axp = (struct ax25_cb *)htol(argv[1]);
  55.     if(!ax25val(axp)){
  56.         printf(notval);
  57.         return 1;
  58.     }
  59.     reset_ax25(axp);
  60.     return 0;
  61. }
  62.  
  63. /* Display AX.25 link level control blocks */
  64. static
  65. doaxstat(argc,argv)
  66. int argc;
  67. char *argv[];
  68. {
  69.     register int i;
  70.     register struct ax25_cb *axp;
  71.     char tmp[10];
  72.     extern char notval[];
  73.  
  74.     if(argc < 2){
  75.         printf("    &AXB IF   Snd-Q   Rcv-Q   Remote    State\n");
  76.         for(i=0;i<NHASH;i++){
  77.             for(axp = ax25_cb[i];axp != NULLAX25; axp = axp->next){
  78.                 pax25(tmp,&axp->addr.dest);
  79.                 printf("%8lx %-5s%-8d%-8d%-10s%s\n",
  80.                     (long)axp,axp->interface->name,
  81.                     len_q(axp->txq),len_mbuf(axp->rxq),
  82.                     tmp,ax25states[axp->state]);
  83.             }
  84.         }
  85.         return 0;
  86.     }
  87.     axp = (struct ax25_cb *)htol(argv[1]);
  88.     if(!ax25val(axp)){
  89.         printf(notval);
  90.         return 1;
  91.     }
  92.     dumpstat(axp);
  93.     return 0;
  94. }
  95. /* Dump one control block */
  96. static
  97. dumpstat(axp)
  98. register struct ax25_cb *axp;
  99. {
  100.     char tmp[10];
  101.     int i;
  102.  
  103.     if(axp == NULLAX25 || axp->interface == NULLIF)
  104.         return;
  105.     printf("&AXB IF   Remote   RB V(S) V(R) Unack P Retry State\n");
  106.     pax25(tmp,&axp->addr.dest);
  107.     printf("%4x %-5s%-9s",(int)axp,axp->interface->name,tmp);
  108.     putchar(axp->rejsent ? 'R' : ' ');
  109.     putchar(axp->remotebusy ? 'B' : ' ');
  110.     printf(" %4d %4d",axp->vs,axp->vr);
  111.     printf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  112.     printf(" %02u/%02u",axp->retries,axp->n2);
  113.     printf(" %s\n",ax25states[axp->state]);
  114.  
  115.     printf("T1: ");
  116.     if(run_timer(&axp->t1))
  117.         printf("%lu",(axp->t1.start - axp->t1.count) * MSPTICK);
  118.     else
  119.         printf("stop");
  120.     printf("/%lu ms; ",axp->t1.start * MSPTICK);
  121.  
  122.     printf("T2: ");
  123.     if(run_timer(&axp->t2))
  124.         printf("%lu",(axp->t2.start - axp->t2.count) * MSPTICK);
  125.     else
  126.         printf("stop");
  127.     printf("/%lu ms; ",axp->t2.start * MSPTICK);
  128.  
  129.     printf("T3: ");
  130.     if(run_timer(&axp->t3))
  131.         printf("%lu",(axp->t3.start - axp->t3.count) * MSPTICK);
  132.     else
  133.         printf("stop");
  134.     printf("/%lu ms\n",axp->t3.start * MSPTICK);
  135.  
  136.     if(axp->addr.ndigis == 0)
  137.         return;
  138.     printf("Digipeaters:");
  139.     for(i=0;i<axp->addr.ndigis;i++){
  140.         pax25(tmp,&axp->addr.digis[i]);
  141.         printf(" %s",tmp);
  142.     }
  143.     printf("\n");
  144. }
  145.  
  146. /* Display or change our AX.25 address */
  147. static
  148. domycall(argc,argv)
  149. int argc;
  150. char *argv[];
  151. {
  152.     char buf[15];
  153.  
  154.     if(argc < 2){
  155.         pax25(buf,&mycall);
  156.         printf("%s\n",buf);
  157.         return 0;
  158.     }
  159.     if(setcall(&mycall,argv[1]) == -1)
  160.         return -1;
  161.     mycall.ssid |= E;
  162.     return 0;
  163. }
  164.  
  165. /* Control AX.25 digipeating */
  166. static
  167. dodigipeat(argc,argv)
  168. int argc;
  169. char *argv[];
  170. {
  171.     extern int digipeat;
  172.  
  173.     if(argc == 1) {
  174.         printf("digipeat %s\n",digipeat ? "on" : "off");
  175.     } else {
  176.         if(strcmp(argv[1],"on") == 0)
  177.             digipeat = 1;
  178.         else
  179.             digipeat = 0;
  180.     }
  181. }
  182.  
  183. /* Set retransmission timer */
  184. static
  185. dot1(argc,argv)
  186. int argc;
  187. char *argv[];
  188. {
  189.     extern int16 t1init;
  190.  
  191.     if(argc == 1) {
  192.         printf("T1 %lu ms\n",(long)t1init * MSPTICK);
  193.     } else {
  194.         t1init = atol(argv[1]) / MSPTICK;
  195.     }
  196. }
  197.  
  198. /* Set acknowledgement delay timer */
  199. static
  200. dot2(argc,argv)
  201. int argc;
  202. char *argv[];
  203. {
  204.     extern int16 t2init;
  205.  
  206.     if(argc == 1) {
  207.         printf("T2 %lu ms\n",(long)t2init * MSPTICK);
  208.     } else {
  209.         t2init = atol(argv[1]) / MSPTICK;
  210.     }
  211. }
  212.  
  213. /* Set idle timer */
  214. static
  215. dot3(argc,argv)
  216. int argc;
  217. char *argv[];
  218. {
  219.     extern int16 t3init;
  220.  
  221.     if(argc == 1) {
  222.         printf("T3 %lu ms\n",(long)t3init * MSPTICK);
  223.     } else {
  224.         t3init = atol(argv[1]) / MSPTICK;
  225.     }
  226. }
  227.  
  228. /* Set retry limit count */
  229. static
  230. don2(argc,argv)
  231. int argc;
  232. char *argv[];
  233. {
  234.     extern int16 n2;
  235.  
  236.     if(argc == 1) {
  237.         printf("Retry %u\n",n2);
  238.     } else {
  239.         n2 = atoi(argv[1]);
  240.     }
  241. }
  242.  
  243. /* Set maximum number of frames that will be allowed in flight */
  244. static
  245. domaxframe(argc,argv)
  246. int argc;
  247. char *argv[];
  248. {
  249.     extern int16 maxframe;
  250.  
  251.     if(argc == 1) {
  252.         printf("Maxframe %u\n",maxframe);
  253.     } else {
  254.         maxframe = atoi(argv[1]);
  255.     }
  256. }
  257.  
  258. /* Set maximum length of I-frame data field */
  259. static
  260. dopaclen(argc,argv)
  261. int argc;
  262. char *argv[];
  263. {
  264.     extern int16 paclen;
  265.  
  266.     if(argc == 1) {
  267.         printf("Paclen %u\n",paclen);
  268.     } else {
  269.         paclen = atoi(argv[1]);
  270.     }
  271. }
  272. /* Set size of I-frame above which polls will be sent after a timeout */
  273. static
  274. dopthresh(argc,argv)
  275. int argc;
  276. char *argv[];
  277. {
  278.     extern int16 pthresh;
  279.  
  280.     if(argc == 1) {
  281.         printf("Pthresh %u\n",pthresh);
  282.     } else {
  283.         pthresh = atoi(argv[1]);
  284.     }
  285. }
  286.  
  287. /* Set high water mark on receive queue that triggers RNR */
  288. static
  289. doaxwindow(argc,argv)
  290. int argc;
  291. char *argv[];
  292. {
  293.     extern int16 axwindow;
  294.  
  295.     if(argc == 1) {
  296.         printf("Axwindow %u\n",axwindow);
  297.     } else {
  298.         axwindow = atoi(argv[1]);
  299.     }
  300. }
  301. /* End of ax25 subcommands */
  302.  
  303. /* Initiate interactive AX.25 connect to remote station */
  304. doconnect(argc,argv)
  305. int argc;
  306. char *argv[];
  307.  {
  308.     void ax_rx(),ax_tx(),ax_state();
  309.     int ax_parse();
  310.     struct ax25_addr dest;
  311.     struct ax25 addr;
  312.     struct ax25_cb *open_ax25();
  313.     struct interface *ifp;
  314.     struct session *s;
  315.     extern int16 axwindow;
  316.     int i;
  317.  
  318.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  319.         if(strcmp(argv[1],ifp->name) == 0)
  320.             break;
  321.  
  322.     if(ifp == NULLIF){
  323.         printf("Interface %s unknown\n",argv[1]);
  324.         return 1;
  325.     }
  326.     setcall(&dest,argv[2]);
  327.     /* See if a session already exists */
  328.     for(s = sessions; s < &sessions[nsessions]; s++){
  329.         if(s->type == AX25TNC
  330.          && addreq(&s->cb.ax25_cb->addr.dest,&dest)){
  331. #if    (defined(MAC) || defined(AMIGA))
  332.             printf("Session %lu to %s already exists\n",
  333. #else
  334.             printf("Session %u to %s already exists\n",
  335. #endif
  336.                 s - sessions,argv[2]);
  337.             return 1;
  338.         }
  339.     }
  340.     /* Allocate a session descriptor */
  341.     if((s = newsession()) == NULLSESSION){
  342.         printf("Too many sessions\n");
  343.         return 1;
  344.     }
  345.     if((s->name = malloc((unsigned)strlen(argv[2])+1)) != NULLCHAR)
  346.         strcpy(s->name,argv[2]);
  347.     s->type = AX25TNC;
  348.     s->parse = ax_parse;
  349.     current = s;
  350.     ASSIGN(addr.source,mycall);
  351.     setcall(&addr.dest,argv[2]);
  352.     for(i=3; i < argc; i++)
  353.         setcall(&addr.digis[i-3],argv[i]);
  354.  
  355.     addr.ndigis = i - 3;
  356.     s->cb.ax25_cb = open_ax25(&addr,axwindow,ax_rx,ax_tx,ax_state,ifp,(char *)s);
  357.     go();
  358.     return 0;
  359. }
  360.  
  361.  
  362. /* Display changes in AX.25 state */
  363. void
  364. ax_state(axp,old,new)
  365. struct ax25_cb *axp;
  366. int old,new;
  367. {
  368.     struct session *s;
  369.  
  370.     s = (struct session *)axp->user;
  371.  
  372.     if(current != NULLSESSION && current->type == AX25TNC && current == s){
  373.         /* Don't print transitions between CONNECTED and RECOVERY */
  374.         if(new != RECOVERY && !(old == RECOVERY && new == CONNECTED))
  375.             printf("%s\n",ax25states[new]);
  376.         if(new == DISCONNECTED)
  377.             cmdmode();
  378.         fflush(stdout);
  379.     }
  380.     if(new == DISCONNECTED){
  381.         axp->user = NULLCHAR;
  382.         freesession(s);
  383.     }
  384. }
  385. /* Handle typed characters on AX.25 connection */
  386. int
  387. ax_parse(buf,cnt)
  388. char *buf;
  389. int16 cnt;
  390. {
  391.     struct mbuf *bp;
  392.     register char *cp;
  393.     char c;
  394.  
  395.     if(current == NULLSESSION || current->type != AX25TNC)
  396.         return;    /* "can't happen" */
  397.  
  398.     /* If recording is on, record outgoing stuff too */
  399.     if(current->record != NULLFILE)
  400.         fwrite(buf,1,cnt,current->record);
  401.  
  402.     /* Allocate buffer and start it with the PID */
  403.     bp = alloc_mbuf(cnt+1);
  404.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3;
  405.     bp->cnt++;
  406.  
  407.     /* Copy keyboard buffer to output, stripping line feeds */
  408.     cp = bp->data + 1;
  409.     while(cnt-- != 0){
  410.         c = *buf++;
  411.         if(c != '\n'){
  412.             *cp++ = c;
  413.             bp->cnt++;
  414.         }
  415.     }
  416.     send_ax25(current->cb.ax25_cb,bp);
  417. }
  418. /* Handle new incoming terminal sessions
  419.  * This is the default receive upcall function, used when
  420.  * someone else connects to us
  421.  */
  422. void
  423. ax_incom(axp,cnt)
  424. register struct ax25_cb *axp;
  425. int16 cnt;
  426. {
  427.     struct session *s;
  428.     char remote[10];
  429.     void ax_rx(),ax_state(),ax_tx();
  430.  
  431.     pax25(remote,&axp->addr.dest);
  432.     if((s = newsession()) == NULLSESSION){
  433.         /* Out of sessions */
  434.         disc_ax25(axp);
  435.         return;
  436.     }
  437.     s->type = AX25TNC;
  438.     s->name = malloc((int16)strlen(remote)+1);
  439.     s->cb.ax25_cb = axp;
  440.     s->parse = ax_parse;
  441.     strcpy(s->name,remote);
  442.     axp->r_upcall = ax_rx;
  443.     axp->s_upcall = ax_state;
  444.     axp->t_upcall = ax_tx;
  445.     axp->user = (char *)s;
  446. #if    (defined(MAC) || defined(AMIGA))
  447.     printf("\007Incoming AX25 session %lu from %s\n",s - sessions,remote);
  448. #else
  449.     printf("\007Incoming AX25 session %u from %s\n",s - sessions,remote);
  450. #endif
  451.     fflush(stdout);
  452. }
  453.  
  454. /* Handle incoming terminal traffic */
  455. void
  456. ax_rx(axp,cnt)
  457. struct ax25_cb *axp;
  458. int16 cnt;
  459. {
  460.     register struct mbuf *bp;
  461.     struct mbuf *recv_ax25();
  462.     char c;
  463.  
  464.     /* Hold output if we're not the current session */
  465.     if(mode != CONV_MODE || current == NULLSESSION
  466.      || current->type != AX25TNC || current->cb.ax25_cb != axp)
  467.         return;
  468.  
  469.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)
  470.         return;
  471.  
  472.     /* Display received characters, translating CR's to CR/LF */
  473.     while(bp != NULLBUF){
  474.         while(bp->cnt-- != 0){
  475.             c = *bp->data++;
  476.             if(c == '\r')
  477.                 c = '\n';
  478.             putchar(c);
  479.             if(current->record){
  480. #ifndef UNIX
  481.                 if(c == '\n')
  482.                     fputc('\r',current->record);
  483. #endif
  484.                 fputc(c,current->record);
  485.             }
  486.         }
  487.         bp = free_mbuf(bp);
  488.     }
  489.     if(current->record)
  490.         fflush(current->record);
  491.     fflush(stdout);
  492. }
  493. /* Handle transmit upcalls. Used only for file uploading */
  494. void
  495. ax_tx(axp,cnt)
  496. struct ax25_cb *axp;
  497. int16 cnt;
  498. {
  499.     register char *cp;
  500.     struct session *s;
  501.     register struct mbuf *bp;
  502.     int16 size;
  503.     int c;
  504.  
  505.     if((s = (struct session *)axp->user) == NULLSESSION
  506.      || s->upload == NULLFILE)
  507.         return;
  508.     while(cnt != 0){
  509.         size = min(cnt,axp->paclen+1);
  510.         if((bp = alloc_mbuf(size)) == NULLBUF)
  511.             break;
  512.         cp = bp->data;
  513.         /* Start with the PID */
  514.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  515.         bp->cnt++;
  516.  
  517.         /* Now send data characters, translating between local
  518.          * keyboard end-of-line sequences and the (unwritten)
  519.          * AX.25 convention, which is carriage-return only
  520.          */
  521.         while(bp->cnt < size){
  522.             if((c = getc(s->upload)) == EOF)
  523.                 break;
  524. #ifdef    MSDOS
  525.             /* MS-DOS gives cr-lf */
  526.             if(c == '\n')
  527.                 continue;
  528. #endif
  529. #if    (defined(UNIX) || defined(MAC) || defined(AMIGA))
  530.             /* These give lf only */
  531.             if(c == '\n')
  532.                 c = '\r';
  533. #endif
  534.             *cp++ = c;
  535.             bp->cnt++;
  536.         }    
  537.         if(bp->cnt > 1) {
  538.             send_ax25(axp,bp);
  539.         } else {
  540.             /* Empty frame, don't bother sending */
  541.             free_p(bp);
  542.             break;
  543.         }
  544.         cnt -= bp->cnt;
  545.     }
  546.     if(cnt != 0){
  547.         /* Error or end-of-file */
  548.         fclose(s->upload);
  549.         s->upload = NULLFILE;
  550.         free(s->ufile);
  551.         s->ufile = NULLCHAR;
  552.     }
  553. }
  554.  
  555.